package com.bosssoft.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bosssoft.entity.po.FibSealPO;
import com.bosssoft.entity.po.FibVoucherDetailsPO;
import com.bosssoft.entity.po.FibVoucherLocationPO;
import com.bosssoft.entity.vo.FibVoucherDetailsVO;
import com.bosssoft.enums.EleSerCode;
import com.bosssoft.exception.DaoException;
import com.bosssoft.fegin.OssFeginService;
import com.bosssoft.page.PageResult;
import com.bosssoft.response.Result;
import com.bosssoft.service.FibSealService;
import com.bosssoft.service.FibVoucherLocationService;
import com.bosssoft.util.ImageToBytesUtils;
import com.bosssoft.util.PdfSignUtils;
import com.bosssoft.util.SnowflakeIdUtil;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.MakeSignature;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.List;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.List;

import com.bosssoft.mapper.FibVoucherDetailsMapper;
import com.bosssoft.service.FibVoucherDetailsService;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import static com.bosssoft.util.PdfSignUtils.getSignPdf;

/**
 * @author Li kexi
 * Created on 2021/8/20.10:12
 */
@Service
public class FibVoucherDetailsServiceImpl extends ServiceImpl<FibVoucherDetailsMapper, FibVoucherDetailsPO> implements FibVoucherDetailsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MakeSignature.class);
    private static final String KEYSTOREUrl = "fiscal-integration/fib-electronic-server/src/main/resources/sign.keystore";
    private static final String localPath = "fiscal-integration/fib-electronic-server/src/main/resources/pdf/";
    private static final String KEYSTORE = "fiscal-integration/fib-electronic-server/src/main/resources/sign.keystore";

    @Autowired
    private FibVoucherDetailsService voucherDetailsService;

    @Autowired
    private FibVoucherLocationService fibVoucherLocationService;

    @Autowired
    private FibSealService sealService;

    @Autowired
    private OssFeginService ossFeginService;

    @Override
    public int updateBatch(List<FibVoucherDetailsPO> list) {
        return baseMapper.updateBatch(list);
    }

    @Override
    public int updateBatchSelective(List<FibVoucherDetailsPO> list) {
        return baseMapper.updateBatchSelective(list);
    }

    @Override
    public int batchInsert(List<FibVoucherDetailsPO> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public Long insertOrUpdate(FibVoucherDetailsPO record) {
        return baseMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(FibVoucherDetailsPO record) {
        return baseMapper.insertOrUpdateSelective(record);
    }

    @Override
    public String stamp(FibVoucherDetailsVO fibVoucherDetailsVO) {
        if (fibVoucherDetailsVO.getVoucherId() == null) {
            log.error("凭证详细id为空");
            throw DaoException.error(EleSerCode.VOUCHER_DETAILS_ID_IS_NULL);
        }
        if (fibVoucherDetailsVO.getVoucher_location_id() == null) {
            log.error("凭证位置id为空");
            throw DaoException.error(EleSerCode.LOCATION_ID_IS_NULL);
        }
        if (fibVoucherDetailsVO.getSealId() == null) {
            log.error("印章id为空");
            throw DaoException.error(EleSerCode.SEAL_ID_NOT_FOUND);
        }
        //实体类
        FibVoucherLocationPO fibVoucherLocationPO = fibVoucherLocationService.getBaseMapper().selectById(fibVoucherDetailsVO.getVoucher_location_id());
        FibSealPO fibSealPO = sealService.getBaseMapper().selectById(Long.valueOf(fibVoucherDetailsVO.getSealId()));
        FibVoucherDetailsPO fibVoucherDetailsPO = baseMapper.selectById(Long.valueOf(fibVoucherDetailsVO.getVoucherId()));
        if (fibSealPO == null) {
            log.error("印章未被找到_根据id查找");
            throw DaoException.error(EleSerCode.SEAL_NOT_FOUND);
        }
        if (fibVoucherDetailsPO == null) {
            log.error("凭证详细记录未被找到_根据id查找");
            throw DaoException.error(EleSerCode.VOUCHER_DETAILS_NOT_FOUND);
        }
        if (fibVoucherLocationPO == null) {
            log.error("凭证盖章地址记录未被找到_根据id查找");
            throw DaoException.error(EleSerCode.LOCATION_NO_FOUND);
        }
        String finishName = stampByPo(fibSealPO, fibVoucherDetailsPO, fibVoucherLocationPO);
        String finishPath = localPath + finishName;
        //读取本地文件,生成流,封装成文件
        byte[] bytes = readFileFromLocal(finishPath);
        if (bytes == null) {
            log.error("读取本地盖章凭证失败");
            return null;
        }
        //转换成 输入流
        InputStream is = new ByteArrayInputStream(bytes);
        //封装进MockMultipartFile
        MultipartFile multipartFile = null;
        try {
            multipartFile = new MockMultipartFile(finishName, finishName, "application/pdf", is);
        } catch (IOException ioException) {
            ioException.printStackTrace();
            log.error("封装流成文件失败");
            throw DaoException.error(EleSerCode.BYTES_TO_MultipartFile_ERROR);
        }
        String url = null;
        if (multipartFile != null) {
            Result upload = ossFeginService.upload(multipartFile);
            System.out.println("-------------code:"+upload.getCode());
            if (upload != null) {
                url = upload.getData().get("url").toString();
            }
        }
        //更新记录
        if (url != null) {
            fibVoucherDetailsPO.setVoucherUrl(url);
            fibVoucherDetailsPO.setStatus(1);
            System.out.println(fibVoucherDetailsPO.getVersion());
            fibVoucherDetailsPO.setVersion(fibVoucherDetailsPO.getVersion() + 1);
            voucherDetailsService.insertOrUpdate(fibVoucherDetailsPO);
        }
        return url;
    }

    private String stampByPo(FibSealPO fibSealPO, FibVoucherDetailsPO fibVoucherDetailsPO, FibVoucherLocationPO fibVoucherLocationPO) {
        //本地文件地址
        String finishPath;
        //seal图片路径
        String sealUrl = fibSealPO.getSealUrl();
        //凭证路径
        ///如果之前未盖过章,选择noSealUrl,否则选择上次盖完章的地址
        String urlNotSeal = ObjectUtil.isNull(fibVoucherDetailsPO.getVoucherUrl()) ?
                fibVoucherDetailsPO.getVoucherUrlNotSeal() : fibVoucherDetailsPO.getVoucherUrl();
        //以下等于上面的三元
        //如果之前未盖过章,选择noSealUrl
        //if (ObjectUtil.isNull(fibVoucherDetailsPO.getVoucherUrl())) {
        //    urlNotSeal = fibVoucherDetailsPO.getVoucherUrlNotSeal();
        //} else {
        //    //否则选择上次盖完章的地址
        //    urlNotSeal = fibVoucherDetailsPO.getVoucherUrl();
        //}
        //通过雪花算法生成文件名
        long snowflakeSealName = SnowflakeIdUtil.getSnowflakeId();
        finishPath = localPath + snowflakeSealName + ".pdf";
        try {
            //盖章
            getSignPdf(sealUrl, urlNotSeal, finishPath, fibVoucherLocationPO, fibVoucherDetailsPO.getVersion());
            return snowflakeSealName + ".pdf";
        } catch (Exception e) {
            e.printStackTrace();
            log.error("盖章失败");
        }
        return null;
    }

    private byte[] readFileFromLocal(String finishPath) {
        InputStream in = null;
        try {
            in = new FileInputStream(finishPath);
            byte[] buffer = new byte[1024 * 4];
            int n = 0;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            while ((n = in.read(buffer)) != -1) {
                out.write(buffer, 0, n);
            }
            return out.toByteArray();
        } catch (Exception e) {
            log.error("读取文件内容出错");
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return null;
    }


    @Override
    public FibVoucherDetailsPO selectByBgtIdAndCode(Integer voucherCode, Long bgtId) {
        if (ObjectUtils.isEmpty(voucherCode)) {
            log.error("凭证编码不能为空");
            throw DaoException.error(EleSerCode.VOUCHER_CODE_ID_NOT_FOUND);
        }
        if (ObjectUtils.isEmpty(bgtId)) {
            log.error("凭证编号不能为空");
            throw DaoException.error(EleSerCode.VOUCHER_ID_NOT_FOUND);
        }
        QueryWrapper<FibVoucherDetailsPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bgt_id", bgtId);
        queryWrapper.eq("voucher_code", voucherCode);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public FibVoucherDetailsPO selectVoucherById(FibVoucherDetailsVO fibVoucherDetailsVO) {
        //判空
        if (ObjectUtils.isEmpty(fibVoucherDetailsVO.getSealId())) {
            log.error("凭证id不能为空");
            throw DaoException.error(EleSerCode.VOUCHER_DETAILS_ID_IS_NULL);
        }
        return baseMapper.selectById(fibVoucherDetailsVO.getVoucherId());
    }

    @Override
    public PageResult<FibVoucherDetailsPO> voucherPage(Integer current, Integer size, FibVoucherDetailsVO fibVoucherDetailsVO) {
        Page<FibVoucherDetailsPO> page = new Page<>(current, size);
        QueryWrapper<FibVoucherDetailsPO> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(fibVoucherDetailsVO.getVoucherId())) {
            queryWrapper.like("voucher_id", fibVoucherDetailsVO.getVoucherId());
        }
        List<FibVoucherDetailsPO> fibVoucherDetailsPOS = baseMapper.selectList(queryWrapper);
        //Page<FibVoucherDetailsPO> pageList = this.page(page, queryWrapper);
        return new PageResult<>(page,fibVoucherDetailsPOS);
    }
}
